<template>
	<div class="form">
		<el-form :model="formData" :labelWidth="calcLabelWidth()" ref="_tableFormRef">
			<el-row :gutter="20">
				<template v-for="(filedDefineItem, index) in fieldDefines" :key="'tableForm' + index">
					<el-col v-if="isShowForm(filedDefineItem)" :span="paseSpan(filedDefineItem)" style="margin-bottom: 20px">
						<el-form-item :label="filedDefineItem.Label" :prop="filedDefineItem.FieldName" :rules="handleRules(filedDefineItem)" class="form-item">
							<component
								:ref="(el: any) => setRefInfo(el, 'TableForm' + index)"
								:is="getComponent(filedDefineItem.InputType)"
								:inputData="props.inputData"
								:FieldItem="filedDefineItem"
								:filterIdx="index"
								:pageData="{ ...props.pageData, ...(props.rowParams || {}) }"
								v-model="formData[filedDefineItem.FieldName]"
								:located="located"
								@updatePageDataFieldObj="handlerUpdatePageDataFieldObj"
							>
							</component>
						</el-form-item>
					</el-col>
				</template>
			</el-row>
		</el-form>
	</div>
</template>
<script lang="ts" setup name="tableForm">
import { FormItemRule, FormInstance } from 'element-plus';
import { CascadeRelationType, EInputCheckType, ProcessType, TabFieldType, EInputDataType } from '/@/components/Linxyun/custom/DataStructs/commontype';
import { getComponent } from '/@/utils/componentFactory';
import { calcFieldValue } from '/@/components/Linxyun/custom/CustomCommon/lxy_expression.js';
import { isChinese, isEnglish } from '/@/utils/extendMethods';
import localforage from 'localforage';
import { httpReqeustApi } from '/@/api/linxyun/base';
import { createDDE_SA } from '/@/utils/stringUtil';
const props = defineProps<{
	fieldDefines: TabFieldType[];
	OpType: number;
	inputData: Record<string, any>;
	pageData: Record<string, any>;
	rowParams?: Record<string, any>;
}>();
const httpRequest = httpReqeustApi();
const { OpType, inputData, rowParams, fieldDefines } = toRefs(props);
const formData = reactive<Record<string, any>>({});
const located = ref('Add');
const refInfo = ref<Record<string, any>>({});
const tempPageData = reactive({ ...props.pageData });
const _tableFormRef = ref<FormInstance>();
// 远程下拉字段
const selectDField = reactive<string[]>([]);
switch (OpType.value) {
	case 2:
		located.value = 'Add';
		fieldDefines.value.forEach((field) => {
			if (field.InputType === 'select_d') {
				selectDField.push(field.FieldName);
			}
			const FieldName = field.FieldName;
			formData[FieldName] ||= '';
			if (field.DefaultValue) {
				formData[FieldName] = field.DefaultValue;
			} else if (field.InputDataType && field.InputDataType !== EInputDataType.StaticVal) {
				const value = calcFieldValue(field.InputDataType, field.InputDataCfg, props.inputData);
				console.log('value======', value);
				formData[FieldName] = ![undefined, NaN, null, '', 'undefined'].includes(value) ? value : '';
			} else if (field.InputDataType === EInputDataType.StaticVal) {
				formData[FieldName] = field.InputDataCfg;
			}
		});
		break;
	case 3:
		located.value = 'Edit';
		fieldDefines.value.forEach((field) => {
			if (field.InputType === 'select_d') {
				selectDField.push(field.FieldName);
			}
			const FieldName = field.FieldName;
			console.log('Edit', rowParams?.value![FieldName]);
			formData[FieldName] = rowParams?.value![FieldName] || field.DefaultValue || '';
		});
		console.log('Edit formData:', { ...formData });
		break;
	case 6:
		located.value = 'Detail';
		fieldDefines.value.forEach((field) => {
			if (field.InputType === 'select_d') {
				selectDField.push(field.FieldName);
			}
			const FieldName = field.FieldName;
			formData[FieldName] = rowParams?.value![FieldName] || '';
		});
		break;
}
const setRefInfo = (el: any, itemKey: string) => {
	refInfo.value[itemKey] = el;
};
// 是否显示表单
const isShowForm = (tabField: TabFieldType) => {
	if (
		(tabField.AddProcessType === ProcessType.Hidden && located.value === 'Add') ||
		(tabField.EditProcessType === ProcessType.Hidden && located.value === 'Edit')
	) {
		return false;
	}
	return true;
};

// 处理是否必填
const handleRules = (tabField: TabFieldType) => {
	const rules: FormItemRule[] = [];
	// 必填
	if (
		(tabField.AddProcessType === ProcessType.Must && located.value === 'Add') ||
		(tabField.EditProcessType === ProcessType.Must && located.value === 'Edit')
	) {
		const rele: FormItemRule = {};
		rele.required = true;
		rele.trigger = 'blur';
		rele.message = `请输入${tabField.Label}`;
		rules.push(rele);
	}
	// 正则校验
	if (tabField.InputCheck?.isCheck === 1 && tabField.InputCheck.type === EInputCheckType.RegEx) {
		const rele: FormItemRule = {};
		rele.trigger = 'blur';
		rele.message = tabField.InputCheck.tips;
		rele.pattern = tabField.InputCheck.value;
		rules.push(rele);

		// 自定义函数校验
	} else if (tabField.InputCheck?.isCheck === 1 && tabField.InputCheck.type === EInputCheckType.CustomFn) {
		const rele: FormItemRule = {};
		rele.trigger = 'blur';
		rele.required = true;
		try {
			const DDE_SA = createDDE_SA(BASE_API.ENT_CODE || 0, 0, 0);
			const headers = { 'DDE-SA': DDE_SA, 'Content-Type': 'application/json;charset=UTF-8' };
			if (tabField.InputCheck.value.length && !isNaN(Number(tabField.InputCheck!.value))) {
				// const funcs = await loadFuncFromLocal(tabField.InputCheck!.value)
				localforage.getItem('f_func_' + BASE_API.ENT_CODE + '_3_' + tabField.InputCheck!.value).then((rsp: any) => {
					if (rsp == null && tabField.InputCheck != null && tabField.InputCheck.value != null) {
						httpRequest.Post(
							'/eslithe/queryFunctionDefineNew.action',
							{},
							{ PageID: -1, EntCode: BASE_API.ENT_CODE, Type: 2, FunctionID: tabField.InputCheck.value },

							headers
						)
						.then((res) => {
							if (res.success && res.code === '0000') {
								const Records = res.Records || [];
								if (Records.length && Records[0].Functions) {
									const str = Records[0].Functions.replace(/\\\\/g, '');
									const arr = JSON.parse(str);
									const coutomFun = new Function('return ' + arr[0].funcText);
									console.log('coutomFun：', coutomFun);
									rele.validator = (rule, value, callback) => {
										if (value === '' || value === undefined) {
											callback(new Error(`请输入${tabField.Label}`));
										} else {
											coutomFun()(value, callback, props.pageData, { ...props.inputData, ...props.rowParams });
										}
									};
									localforage.setItem('f_func_' + BASE_API.ENT_CODE + '_3_' + tabField.InputCheck!.value, str)
								} else {
									localforage.setItem('f_func_' + BASE_API.ENT_CODE + '_3_' + tabField.InputCheck!.value, 'None')
								}
							}
						});
					} else {
						if (rsp && rsp != 'None') {
							const arr = JSON.parse(rsp);
							const coutomFun = new Function('return ' + arr[0].funcText);
							console.log('coutomFun：', coutomFun);
							rele.validator = (rule, value, callback) => {
								if (value === '' || value === undefined) {
									callback(new Error(`请输入${tabField.Label}`));
								} else {
									coutomFun()(value, callback, props.pageData, { ...props.inputData, ...props.rowParams });
								}
							};
						}
					}
				})
			} else {
				const coutomFun = new Function('return ' + tabField.InputCheck.value);
				// console.log('coutomFun：', coutomFun);
				rele.validator = (rule, value, callback) => {
					if (value === '' || value === undefined) {
						callback(new Error(`请输入${tabField.Label}`));
					} else {
						coutomFun()(value, callback, props.pageData, { ...props.inputData, ...props.rowParams });
					}
				};
			}
		} catch (error) {
			console.error('当前字段函数校验表达式出错，请检查输入的函数表达式');
		}
		rules.push(rele);
	}

	return rules;
};

// 上传文件
const uploadFile = async () => {
	console.log(fieldDefines.value);
	for (let index in fieldDefines.value) {
		if (['el-img', 'video'].includes(fieldDefines.value[index].InputType)) {
			const res = await refInfo.value['TableForm' + index].uploadSubmit();
			const Duration: any[] = refInfo.value['TableForm' + index].videoArr;
			formData[fieldDefines.value[index].FieldName] = fileList2Data(res);
			console.log(`uploadFile `, formData);
			if (fieldDefines.value[index].FieldName === 'Duration') {
				Duration.length === 1 ? (formData['Duration'] = Duration[0].duration) : (formData['Duration'] = JSON.stringify(Duration));
			}
		} else if (fieldDefines.value[index].InputType === 'rich' && fieldDefines.value[index].DataStorageMode === 'file') {
			const content = await refInfo.value['TableForm' + index].uploadSubmit();
			formData[fieldDefines.value[index].FieldName] = content;
		} else if (fieldDefines.value[index].InputType === 'code-editor' && fieldDefines.value[index].DataStorageMode === 'file') {
			const content = await refInfo.value['TableForm' + index].uploadSubmit();
			formData[fieldDefines.value[index].FieldName] = content;
		}
	}
};
const fileList2Data = (fileList: { name: string; url: string }[]) => {
	let data = '';
	for (let i = 0; i < fileList.length; i++) {
		if (i > 0) {
			data += ';';
		}
		data = data + fileList[i].name + ':=' + fileList[i].url;
	}
	return data;
};

const needWatchFieldList = [];
const expFieldIdxList: number[] = [];
for (let i = 0; fieldDefines.value && i < fieldDefines.value.length; i++) {
	// 是否开启监听
	if (fieldDefines.value[i].IfCascadeShow) {
		needWatchFieldList.push(() => formData[fieldDefines.value[i].FieldName]);
	}
	if (
		fieldDefines.value[i].InputDataType === EInputDataType.Exp &&
		selectDField.findIndex((field: string) => fieldDefines.value[i].InputDataCfg!.includes(field)) == -1
	) {
		expFieldIdxList.push(i);
	}
}

// 监听依赖并更新指定字段
watch(
	needWatchFieldList,
	() => {
		// console.log('needWatchFieldList watch', newVal);
		updateDependVal(expFieldIdxList, formData);
	},
	{
		immediate: true,
	}
);

const paseSpan = (filedDefineItem: TabFieldType) => {
	if (filedDefineItem.AddColWidth) {
		if (Number(filedDefineItem.AddColWidth) > 24 || Number(filedDefineItem.AddColWidth) === 0) {
			return 24;
		} else {
			return Number(filedDefineItem.AddColWidth);
		}
	} else if (filedDefineItem.EditColWidth) {
		if (Number(filedDefineItem.EditColWidth) > 24 || Number(filedDefineItem.EditColWidth) === 0) {
			return 24;
		} else {
			return Number(filedDefineItem.EditColWidth);
		}
	}
	console.log('paseSpan', filedDefineItem);
	return 24;
};

// 计算表单label宽度
const calcLabelWidth = () => {
	let defaultLength = 100;
	for (let index = 0; index < fieldDefines.value.length; index++) {
		const field = fieldDefines.value[index];
		if (located.value === 'Add' && ![ProcessType.Process, ProcessType.Must, ProcessType.Readonly].includes(field.AddProcessType!)) {
			continue;
		} else if (located.value === 'Edit' && ![ProcessType.Process, ProcessType.Must, ProcessType.Readonly].includes(field.EditProcessType!)) {
			continue;
		}
		let charsLength = 0;
		for (let index = 0; index < field.Label.length; index++) {
			const char = field.Label[index];
			if (isChinese(char)) {
				charsLength += 16;
			} else if (isEnglish(char)) {
				charsLength += 10;
			}
		}
		if (charsLength > defaultLength) {
			defaultLength = charsLength;
		}
	}
	return defaultLength;
};
/**
 * 控制是否级联
 * 描述：其他组件可以获取下拉组件当前选择的值对应项里的参数。
 * 示例：下拉组件字段名拼接Obj.xxxx '${xxxObj.xxxx}'
 * @param cascadeObj
 * @param FieldName
 */
const handlerUpdatePageDataFieldObj = (cascadeObj: Record<string, any>, FieldName: string) => {
	console.log('handlerUpdatePageDataFieldObj', FieldName, cascadeObj);
	console.log('pageData:', { ...tempPageData, ...(rowParams?.value || {}) });
	tempPageData[FieldName] = cascadeObj;
	for (let i = 0; i < fieldDefines.value.length; i++) {
		const field = fieldDefines.value[i];
		const { InputDataCfg } = field;
		if (field.InputDataType && field.InputDataType === 4 && InputDataCfg!.includes(FieldName)) {
			const value = calcFieldValue(field.InputDataType, field.InputDataCfg, {}, { ...tempPageData, ...(rowParams?.value || {}) });
			console.log('FieldName:', field.FieldName, 'value:', value);
			formData[field.FieldName] = ![undefined, NaN, null, '', 'undefined'].includes(value) ? value : '';
			console.log('handlerUpdatePageDataFieldObj formData', formData[field.FieldName]);
		}
	}
};

function updateDependVal(upFieldIdxList: number[], pageData: Record<string, any>) {
	console.log('updateDependVal:', upFieldIdxList, pageData);
	for (let index = 0; index < upFieldIdxList.length; index++) {
		const idx = upFieldIdxList[index];
		const fieldConfig = fieldDefines.value[idx];
		if (fieldConfig) {
			const value = calcFieldValue(fieldConfig.InputDataType, fieldConfig.InputDataCfg, {}, { ...tempPageData, ...pageData });
			formData[fieldConfig.FieldName] = ![undefined, NaN, null, '', 'undefined'].includes(value) ? value : '';
		}
	}
}
defineExpose({
	_tableFormRef,
	formData,
	uploadFile,
});
</script>
<style scoped>
.el-form-item :deep(.el-form-item__label) {
	justify-content: flex-start;
}
.form {
	background-color: var(--next-color-white);
	padding: 10px;
}
</style>
